package com.wut.clock.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wut.clock.common.constant.ClockConstant;
import com.wut.clock.common.exception.Asserts;
import com.wut.clock.common.service.RedisService;
import com.wut.clock.common.util.ClockUtil;
import com.wut.clock.config.MailClient;
import com.wut.clock.dto.admin.ShiroSysUser;
import com.wut.clock.entity.Favorite;
import com.wut.clock.entity.SysUser;
import com.wut.clock.mapper.FavoriteMapper;
import com.wut.clock.mapper.SysUserMapper;
import com.wut.clock.service.IUserService;
import com.wut.clock.util.Md5Util;
import com.wut.clock.vo.admin.LoginVo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;

import java.util.Random;

/**
 * @author ZYH
 * @unit D9Lab
 * @description TODO
 * @date 2022/6/7 11:29
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements IUserService {

    private final SysUserMapper userMapper;

    private final RedisService redisService;

    private final MailClient mailClient;

    private final FavoriteMapper favoriteMapper;

    @Override
    public boolean sendRegisterMail(String type, String email) {
        String key = type +email;
        if("注册用户".equals(type)){
            SysUser findUserMail = userMapper.selectOne(new QueryWrapper<SysUser>().eq("email", email));
            if(findUserMail != null) Asserts.fail("该邮箱已经被注册!");
        }
        if(redisService.get(key) != null) Asserts.fail("验证码已经存在，请检查邮箱！");
        // 生成一个4位的随机注册码
        String code = ClockUtil.generateUuid().substring(0, 4);
        mailClient.sendMail(email,type,"请使用以下验证码: "+code+" ,3分钟之内有效!");
        // 设置成3分钟
        redisService.set(key,code,180);
        return true;
    }

    @Override
    public int registerUser(String username, String password, String confirmPassword, String email, String code) {
        // 后端判断用户是否已经存在以及邮箱是否已经注册过
        SysUser findUsername = userMapper.selectOne(new QueryWrapper<SysUser>().eq("username", username));
        if(findUsername != null) Asserts.fail("用户已经存在");
        SysUser findUserMail = userMapper.selectOne(new QueryWrapper<SysUser>().eq("email", email));
        if(findUserMail != null) Asserts.fail("该邮箱已经被注册");
        // 注册用户
        SysUser user = new SysUser();
        user.setUsername(username);
        user.setEmail(email);
        // 需要将密码加密
        user.setPassword(Md5Util.encrypt(password));
        // 给用户头像和昵称赋予初值
        user.setNickname("ClockUser"+ClockUtil.generateUuid().substring(0,3));
        //https://himg.bdimg.com/sys/portrait/hotitem/wildkid/1-67
        user.setAvatar("https://himg.bdimg.com/sys/portrait/hotitem/wildkid/"+new Random().nextInt(68));
        // 从 redis 中获取验证码
        String key = "注册用户" + email;
        String emailCode = redisService.get(key).toString();
        if(StringUtils.isBlank(emailCode)) Asserts.fail("验证码不存在或者已经失效，请检查邮箱是否正确或重新获取验证码");
        if(!code.equals(emailCode)) Asserts.fail("您输入的验证码错误，请重新验证");
        if(!password.equals(confirmPassword)) Asserts.fail("两次输入的密码不一致,请检查后再次输入");
        int res = userMapper.insert(user);
        // 注册成功,系统自动为该用户设定以下默认条件
        // 1. 系统自动分配一个默认收藏夹
        Favorite favorite = new Favorite();
        favorite.setUserId(user.getId());
        favorite.setFavoriteName(ClockConstant.DEFAULT_FAVORITE);
        favorite.setFavoriteRemark(ClockConstant.DEFAULT_FAVORITE_REMARK);
        favoriteMapper.insert(favorite);
        return res;
    }

    @Override
    public int forgetPassword(String email, String code, String password, String confirmPassword) {
        SysUser user = userMapper.selectOne(new QueryWrapper<SysUser>().eq("email", email));
        if(user == null) Asserts.fail("用户不存在,请检验邮箱是否正确");
        String key = "忘记密码" + email;
        String emailCode = redisService.get(key).toString();
        if(StringUtils.isBlank(emailCode)) Asserts.fail("验证码不存在或者已经失效，请检查邮箱是否正确或重新获取验证码");
        if(!code.equals(emailCode)) Asserts.fail("验证码错误，请查看邮箱");
        if(!password.equals(confirmPassword)) Asserts.fail("两次输入的密码不一致");
        user.setPassword(Md5Util.encrypt(password));
        return userMapper.updateById(user);
    }

    @Override
    public LoginVo login(String username, String password) {
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
        } catch (Exception e) {
            Asserts.fail("登录失败，请输入正确的用户名和密码！");
        }
        ShiroSysUser shiroSysUser = (ShiroSysUser) subject.getPrincipal();
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(subject.getSession().getId());
        loginVo.setUserId(shiroSysUser.getUserId());
        loginVo.setUsername(shiroSysUser.getUsername());
        loginVo.setNickName(userMapper.selectById(shiroSysUser.getUserId()).getNickname());
        return loginVo;
    }
}
